using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Splino
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            ApplicationHelper.Instance.Run();
        }
    };

    /// <summary>
    /// Handles the application's idle loop.
    /// </summary>
    public sealed class ApplicationHelper
    {
        bool _idleEventHooked = false;
        bool _idleResetEventHooked = false;

        private static readonly ApplicationHelper instance = new ApplicationHelper();
        private ApplicationHelper() { }
        /// <summary>
        /// The singleton instance of ApplicationHelper
        /// </summary>
        public static ApplicationHelper Instance { get { return instance; } }

        /// <summary>
        /// An extension of Application.Run() that hooks into
        /// the Application.Idle event to call Render()
        /// </summary>
        public void Run()
        {
            Form splinoForm = SplinoForm.Instance;
            HookIdleDrawEvent();
            Application.Run(splinoForm);
        }

        // Event handler for Application.Idle
        // Invalidates the SplinoForm, which in turn calls Render()
        // and loops back to the start when the application goes idle 
        private void OnApplicationIdle(object sender, EventArgs e)
        {
            if (SplinoForm.Instance.ContinuousRenderingMode)
                SplinoForm.Instance.Invalidate();
            else if (D3D.DeviceManager.Instance.RenderRequested)
                SplinoForm.Instance.Invalidate();
        }

        private void OnApplicationIdleDeviceReset(object sender, EventArgs e)
        {
            Splino.D3D.DeviceManager.Instance.AttemptDeviceReset();
        }

        /// <summary>
        /// Unhooks the Application.Idle event handlers
        /// </summary>
        public void UnhookIdleDrawEvent()
        {
            if (_idleEventHooked)
            {
                Application.Idle -= new EventHandler(OnApplicationIdle);
                _idleEventHooked = false;
            }
        }

        /// <summary>
        /// Hooks the Application.Idle event to the event handler
        /// OnApplicationIdle().
        /// </summary>
        public void HookIdleDrawEvent()
        {
            if (!_idleEventHooked)
            {
                Application.Idle += new EventHandler(OnApplicationIdle);
                _idleEventHooked = true;
            }
        }

        /// <summary>
        /// Hooks the Application.Idle event to an event handler that
        /// attempts to reset the Direct3D device.
        /// </summary>
        public void HookIdleResetEvent()
        {
            if (!_idleResetEventHooked)
            {
                Application.Idle += new EventHandler(OnApplicationIdleDeviceReset);
                _idleResetEventHooked = true;
            }
        }

        /// <summary>
        /// Unhooks the Application.Idle event to an event handler that
        /// attempts to reset the Direct3D device.
        /// </summary>
        public void UnhookIdleResetEvent()
        {
            if (_idleResetEventHooked)
            {
                Application.Idle -= new EventHandler(OnApplicationIdleDeviceReset);
                _idleResetEventHooked = false;
            }
        }
    };
}